package com.signin.handler;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.signin.model.dto.SignInSessionDTO;
import com.signin.model.dto.StudentSignInDTO;
import com.signin.model.entity.SignInRecord;
import com.signin.service.SignInService;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class WebSocketServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    private static final ObjectMapper objectMapper = new ObjectMapper();

    private static SignInService signInService;

    @Autowired
    public void setSignInService(SignInService service) {
        signInService = service;
    }

    // 处理WebSocket连接
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        channels.add(ctx.channel());
        System.out.println("Client connected: " + ctx.channel().remoteAddress());
    }

    // 处理接收到的WebSocket消息
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) throws Exception {
        String message = frame.text();
        System.out.println("Received message: " + message);

        try {
            Map<String, Object> data = objectMapper.readValue(message, HashMap.class);
            String type = (String) data.get("type");

            switch (type) {
                case "startSignIn":
                    handleStartSignIn(ctx, data);
                    break;
                case "endSignIn":
                    handleEndSignIn(ctx, data);
                    break;
                case "studentSignIn":
                    handleStudentSignIn(ctx, data);
                    break;
                case "queryActiveSession":
                    handleQueryActiveSession(ctx);
                    break;
                case "queryActiveSessionByClassroom":
                    handleQueryActiveSessionByClassroom(ctx, data);
                    break;
                case "querySignInRecords":
                    handleQuerySignInRecords(ctx, data);
                    break;
                default:
                    System.out.println("Unknown message type: " + type);
            }
        } catch (Exception e) {
            e.printStackTrace();
            sendErrorMessage(ctx, "处理消息失败: " + e.getMessage());
        }
    }

    // 处理WebSocket连接关闭
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        channels.remove(ctx.channel());
        System.out.println("Client disconnected: " + ctx.channel().remoteAddress());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

    // 处理开始签到
    private void handleStartSignIn(ChannelHandlerContext ctx, Map<String, Object> data) throws Exception {
        Long sessionId = Long.valueOf(data.get("sessionId").toString());
        boolean success = signInService.startSignIn(sessionId);

        Map<String, Object> response = new HashMap<>();
        response.put("type", "signInStarted");
        response.put("success", success);
        response.put("sessionId", sessionId);

        sendMessage(ctx, response);

        // 广播签到开始消息给所有客户端
        if (success) {
            // 获取当前签到会话的教室信息
            SignInSessionDTO sessionDTO = signInService.getSignInSession(sessionId);
            String classroom = sessionDTO != null ? sessionDTO.getClassroom() : "";
            
            Map<String, Object> broadcast = new HashMap<>();
            broadcast.put("type", "signInSessionActive");
            broadcast.put("sessionId", sessionId);
            broadcast.put("classroom", classroom); // 添加教室信息
            broadcastMessage(broadcast);
        }
    }

    // 处理结束签到
    private void handleEndSignIn(ChannelHandlerContext ctx, Map<String, Object> data) throws Exception {
        Long sessionId = Long.valueOf(data.get("sessionId").toString());
        boolean success = signInService.endSignIn(sessionId);

        Map<String, Object> response = new HashMap<>();
        response.put("type", "signInEnded");
        response.put("success", success);
        response.put("sessionId", sessionId);

        sendMessage(ctx, response);

        // 广播签到结束消息给所有客户端
        if (success) {
            // 获取当前签到会话的教室信息
            SignInSessionDTO sessionDTO = signInService.getSignInSession(sessionId);
            String classroom = sessionDTO != null ? sessionDTO.getClassroom() : "";
            
            Map<String, Object> broadcast = new HashMap<>();
            broadcast.put("type", "signInSessionEnded");
            broadcast.put("sessionId", sessionId);
            broadcast.put("classroom", classroom); // 添加教室信息
            broadcastMessage(broadcast);
        }
    }

    // 处理学生签到
    private void handleStudentSignIn(ChannelHandlerContext ctx, Map<String, Object> data) throws Exception {
        Long sessionId = Long.valueOf(data.get("sessionId").toString());
        Map<String, String> signInData = (Map<String, String>) data.get("data");

        StudentSignInDTO signInDTO = new StudentSignInDTO();
        signInDTO.setStudentName(signInData.get("studentName"));
        signInDTO.setClassroomLocation(signInData.get("classroomLocation"));

        boolean success = signInService.studentSignIn(sessionId, signInDTO);

        Map<String, Object> response = new HashMap<>();
        response.put("type", "signInResult");
        response.put("success", success);
        
        if (success) {
            response.put("message", "签到成功！");
            
            // 获取当前签到会话的教室信息
            SignInSessionDTO sessionDTO = signInService.getSignInSession(sessionId);
            
            // 广播新的签到信息给特定教室的教师
            Map<String, Object> broadcast = new HashMap<>();
            broadcast.put("type", "newSignInRecord");
            broadcast.put("sessionId", sessionId);
            broadcast.put("studentName", signInDTO.getStudentName());
            broadcast.put("classroomLocation", signInDTO.getClassroomLocation());
            broadcast.put("targetClassroom", sessionDTO != null ? sessionDTO.getClassroom() : signInDTO.getClassroomLocation());
            broadcastMessage(broadcast);
        } else {
            response.put("message", "签到失败！可能是签到已结束或您已签到过。");
        }

        sendMessage(ctx, response);
    }

    // 处理查询活动签到会话
    private void handleQueryActiveSession(ChannelHandlerContext ctx) throws Exception {
        SignInSessionDTO sessionDTO = signInService.getCurrentActiveSession();

        Map<String, Object> response = new HashMap<>();
        response.put("type", "activeSession");
        response.put("session", sessionDTO);

        sendMessage(ctx, response);
    }
    
    // 处理按教室查询活动签到会话
    private void handleQueryActiveSessionByClassroom(ChannelHandlerContext ctx, Map<String, Object> data) throws Exception {
        String classroom = (String) data.get("classroom");
        SignInSessionDTO sessionDTO = signInService.getCurrentActiveSessionByClassroom(classroom);

        Map<String, Object> response = new HashMap<>();
        response.put("type", "activeSession");
        response.put("session", sessionDTO);

        sendMessage(ctx, response);
        
        // 如果有活动会话，查询相关的签到记录
        if (sessionDTO != null) {
            handleQuerySignInRecords(ctx, Map.of("sessionId", sessionDTO.getId()));
        } else {
            // 如果没有活动会话，发送空记录列表
            Map<String, Object> emptyRecordsResponse = new HashMap<>();
            emptyRecordsResponse.put("type", "signInRecords");
            emptyRecordsResponse.put("records", List.of());
            sendMessage(ctx, emptyRecordsResponse);
        }
    }

    // 处理查询签到记录
    private void handleQuerySignInRecords(ChannelHandlerContext ctx, Map<String, Object> data) throws Exception {
        Long sessionId = Long.valueOf(data.get("sessionId").toString());
        List<SignInRecord> records = signInService.getSignInRecords(sessionId);

        Map<String, Object> response = new HashMap<>();
        response.put("type", "signInRecords");
        response.put("records", records);

        sendMessage(ctx, response);
    }

    // 广播消息给所有连接的客户端
    public void broadcastMessage(Map<String, Object> message) {
        try {
            String jsonMessage = objectMapper.writeValueAsString(message);
            channels.writeAndFlush(new TextWebSocketFrame(jsonMessage));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 发送消息给特定客户端
    public void sendMessage(ChannelHandlerContext ctx, Map<String, Object> message) {
        try {
            String jsonMessage = objectMapper.writeValueAsString(message);
            ctx.channel().writeAndFlush(new TextWebSocketFrame(jsonMessage));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 发送错误消息
    private void sendErrorMessage(ChannelHandlerContext ctx, String errorMessage) {
        Map<String, Object> response = new HashMap<>();
        response.put("type", "error");
        response.put("message", errorMessage);
        sendMessage(ctx, response);
    }
}